package org.wattdepot.gdata.kukuicup.updater.energybaselines;

import java.net.URL;
import java.text.SimpleDateFormat;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.client.WattDepotClientException;
import org.wattdepot.gdata.kukuicup.service.GDataBatchRequest;
import org.wattdepot.gdata.kukuicup.service.GDataService;
import org.wattdepot.gdata.kukuicup.service.WattDepotService;
import org.wattdepot.gdata.kukuicup.updater.GDataTask;
import org.wattdepot.util.tstamp.Tstamp;
import java.util.Calendar;
import java.util.Locale;

/**
 * Collects daily energy data for the baseline period and writes it out to the spreadsheet.
 * 
 * @author Philip Johnson
 */
public class DailyEnergyBaselinesTask extends GDataTask {

  private static final String startDateKey = "daily.energy.baselines.start.date";
  private static final String endDateKey = "daily.energy.baselines.end.date";
  private XMLGregorianCalendar startDate;
  private XMLGregorianCalendar endDate;
  private String startString;
  private String endString;

  /**
   * Creates the new DailyEnergyBaselinesTask.
   * 
   * @param wattDepotService The WattDepot service configuration data.
   * @param gdataService The gdata service configuration data.
   * @param spreadsheetURL The URL to the spreadsheet containing the data.
   * @param sourceName The WattDepot source of interest.
   * @param isVirtual True if the source is virtual.
   * @param row The row in the spreadsheet that this source's data appears in.
   */
  public DailyEnergyBaselinesTask(WattDepotService wattDepotService, GDataService gdataService,
      URL spreadsheetURL, String sourceName, boolean isVirtual, int row) {
    super(wattDepotService, gdataService, spreadsheetURL, sourceName, row, "DailyEnergyBaselines",
        isVirtual);
    this.startString = wattDepotService.getProperties().getRequiredProperty(startDateKey);
    this.endString = wattDepotService.getProperties().getRequiredProperty(endDateKey);
    SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
    try {
      this.startDate = Tstamp.makeTimestamp(dateFormat.parse(startString).getTime());
      this.endDate = Tstamp.makeTimestamp(dateFormat.parse(endString).getTime());
    }
    catch (Exception e) {
      throw new RuntimeException("Error parsing dailyenergybaseline start or end date.", e);
    }
  }

  /**
   * Collects the daily baseline data and updates the spreadsheet.
   */
  @Override
  public void run() {
    //System.out.format("DailyEnergyBaselines: %s, %s, %s%n", sourceName, startDate, endDate);
    WattDepotClient client = this.wattDepotService.getClient();
    BaselineDataSet dataSet = new BaselineDataSet();

    startWattDepotTiming();

    // Loop through all days between startDate and endDate.
    for (XMLGregorianCalendar beginningOfDay = this.startDate; beginningOfDay.toGregorianCalendar()
        .getTimeInMillis() <= this.endDate.toGregorianCalendar().getTimeInMillis(); 
        beginningOfDay = Tstamp.incrementDays(beginningOfDay, 1)) {
      XMLGregorianCalendar endingOfDay = Tstamp.incrementDays(beginningOfDay, 1);
      Integer energy = 0;
      try {
        energy = (int) client.getEnergyConsumed(sourceName, beginningOfDay, endingOfDay, 120);
        // System.out.format("Found energy %s for %s at %s%n", energy, sourceName, beginningOfDay);
        // Update the data structure with this day's data.
        int dayOfWeek = beginningOfDay.toGregorianCalendar().get(Calendar.DAY_OF_WEEK);
        dataSet.add(dayOfWeek, energy);
      }
      catch (WattDepotClientException e) {
        System.out.format("Failed to get energy for %s for day %s%n", sourceName, beginningOfDay);
      }
    }

    stopWattDepotTiming();

    try {
      startGDataTiming();
      // Now update the spreadsheet with all of the data.
      GDataBatchRequest request = new GDataBatchRequest(gdataService, spreadsheetURL);
      // Update the lastUpdate cell
      request.addRequest(this.row, 2, gdataService.makeLastUpdate());
      // Update the start and end date cells
      request.addRequest(this.row, 3, this.startString);
      request.addRequest(this.row, 4, this.endString);

      // Update the remaining columns with the daily baseline data.
      int column = 5;
      for (int day = 1; day <= 7; day++) {
        String baseline = String.valueOf((int) dataSet.getAverage(day));
        request.addRequest(this.row, column, baseline);
        column++;
      }
      request.sendRequest();
      stopGDataTiming();
      String numBaselines = String.valueOf(dataSet.getTotalEntries());
      printTaskResults(numBaselines + " baselines", "kWh", "OK");
    }
    catch (Exception e) {
      System.out.format("Problem getting baseline for source %s: %s%n", sourceName, e.getMessage());
    }

  }

}
